package com.sanshow.charging.util;

import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.CacheDoubleUtils;
import com.blankj.utilcode.util.CacheMemoryUtils;
import com.blankj.utilcode.util.ProcessUtils;
import com.blankj.utilcode.util.SPUtils;
import com.blankj.utilcode.util.TimeUtils;
import com.sanshow.charging.MainActivity;
import com.sanshow.charging.MyApplication;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局捕获异常
 * 当程序发生Uncaught异常的时候,有该类来接管程序,并记录错误日志
 */
public class CrashHandler_Ma {
    public static String TAG = "MyCrash";
    // 用来存储设备信息和异常信息
    private static Map<String, String> map = new HashMap<>();

    //使用volatile关键字保其可见性
    volatile private static CrashHandler_Ma instance = null;

    private CrashHandler_Ma() {
    }

    public static CrashHandler_Ma getInstance() {
        try {
            if (instance != null) {//懒汉式

            } else {
                //创建实例之前可能会有一些准备性的耗时工作
                Thread.sleep(300);
                synchronized (CrashHandler_Ma.class) {
                    if (instance == null) {//二次检查
                        instance = new CrashHandler_Ma();
                    }
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return instance;
    }

    public void init(Context context) {
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                try {
                    Log.e(TAG, "uncaughtException: " + ex);
                    if (ex != null) {
                        // 使用Toast来显示异常信息
                        new Thread() {
                            @Override
                            public void run() {
                                Looper.prepare();
                                Toast.makeText(context, "APP运行缓慢,自动重启中,请稍等！\n暂时不要做任何借还、关门操作", Toast.LENGTH_LONG).show();
                                Looper.loop();
                            }
                        }.start();

                        //saveCrashInfoFile(ex, context);
                        Log.e(TAG,"系统奔溃了，正在重启中");
                        SPUtils.getInstance().put("nowSaveDataTimeStamp", TimeUtils.getNowMills()/1000);
                        SystemClock.sleep(1000);
                        restartApp();
                    }
                } catch (Exception e) {
                    SystemClock.sleep(1000);
                    // 退出程序
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(1);
                }
            }
        });
    }

    /**
     * 保存错误信息到文件中
     *
     * @return 返回文件名称, 便于将文件传送到服务器
     */
    private void saveCrashInfoFile(Throwable ex, Context context) {
        try {
            map.put("versionName", AppInfoUtils.getVersionName());
            map.put("versionCode", AppInfoUtils.getVersionCode() + "");
            /*收集设备参数信息*/
            Field[] fields = Build.class.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(null).toString());
            }
        } catch (Exception e) {

        }

        StringBuffer sb = new StringBuffer();
        try {
            SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date = sDateFormat.format(new Date());
            sb.append("\r\n" + date + "\n");
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                sb.append(key + "=" + value + "\n");
            }
            Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            ex.printStackTrace(printWriter);
            Throwable cause = ex.getCause();
            while (cause != null) {
                cause.printStackTrace(printWriter);
                cause = cause.getCause();
            }
            printWriter.flush();
            printWriter.close();
            String result = writer.toString();
            sb.append(result);

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                ActivityManager activityManager = (ActivityManager) MyApplication.getContext().getSystemService(Context.ACTIVITY_SERVICE);
                ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
                activityManager.getMemoryInfo(info);
                long mm = 1024 * 1024;
                sb.append("\n应用在本机能够获取的最大内存：" + DoubleUtil.divLong(Runtime.getRuntime().maxMemory(), mm) + "m")
                        .append("\n系统剩余内存: " + DoubleUtil.divLong(info.availMem, mm) + "m")
                        .append("\n系统是否处于低内存运行：" + info.lowMemory)
                        .append("\n系统总的内存：" + DoubleUtil.divLong(info.totalMem, mm) + "m")
                        .append("\n临界值，达到这个值，进程就要被杀死：" + DoubleUtil.divLong(info.threshold, mm) + "m");
            }
        } catch (Exception e) {
            sb.append("an error occured while writing file...\r\n");
        }
        // 把这个错误信息保存到数据库里面了，等到下次进首页的时候，把数据库里面的错误信息传到服务器，便于后续分析
        //LiteOrmDBUtil.insert(new Bean_ERROR(0, sb.toString()));
        sb.setLength(0);
    }

    /*重启应用（按需要添加是否重启应用）*/
    public void restartApp() {
        MainActivity.releaseActivity();
        ActivityUtils.finishActivity(MainActivity.class);
        AppUtils.relaunchApp(true);
    }
}
